package com.why.cachecloud.service.custom;

import com.why.cachecloud.configuration.constant.AppStatusEnum;
import com.why.cachecloud.configuration.exception.SSHException;
import com.why.cachecloud.dao.InstanceDao;
import com.why.cachecloud.entity.AppDesc;
import com.why.cachecloud.entity.InstanceInfo;
import com.why.cachecloud.service.ssh.SSHService;
import com.why.cachecloud.web.service.AppService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;

/**
 * 实例真实状态的检测
 */
@Slf4j
@Component
public class InstanceActualStatusService {

    @Resource
    private InstanceDao instanceDao;
    @Resource
    private AppService appService;
    @Resource
    private SSHService sshService;

    public void check() {
        log.info("检测离线节点是否正常下线开始...");
        List<InstanceInfo> infoList = instanceDao.getOfflineListByStatusList();
        if (infoList.isEmpty()) {
            log.info("检测离线节点是否正常下线结束,离线实例为空..");
            return;
        }

        Map<Long, AppDesc> map = new HashMap<>();
        int kill = 0;

        for (InstanceInfo instanceInfo : infoList) {
            long appId = instanceInfo.getAppId();

            AppDesc appDesc = map.computeIfAbsent(appId, key -> appService.getByAppId(key));

            //   已下线或者驳回的
            if (appDesc.getStatus() > AppStatusEnum.STATUS_INITIALIZE.getStatus() && appDesc.getStatus() < AppStatusEnum.STATUS_OFFLINE.getStatus()) {
                continue;
            }

            String ip = instanceInfo.getIp();

            String cmd = "/usr/sbin/lsof -i:" + instanceInfo.getPort();
            try {
                String result = sshService.execute(ip, cmd);
                log.info("appId:{},appName:{},ip:{},port:{},exec cmd:{},result:{}", appId, appDesc.getName(), ip, instanceInfo.getPort(), cmd, result);
                if (result == null) {
                    continue;
                }
                String pid = parsePid(result);
                log.info("appId:{},appName:{},ip:{},port:{},exec cmd:{},result:{},pid:{}", appId, appDesc.getName(), ip, instanceInfo.getPort(), cmd, result, pid);
                if (pid != null) {
                    String killCmd = "/usr/bin/kill -9 " + pid;
                    String execute = sshService.execute(ip, killCmd);
                    log.info("appId:{},appName:{},to ip:{},exec kill cmd:{},result:{}", appId, appDesc.getName(), ip, killCmd, execute);
                    kill++;
                }
            } catch (SSHException e) {
                e.printStackTrace();
            }
        }
        log.info("检测离线节点是否正常下线结束,检测离线实例记录:{},kill实例记录:{}", infoList.size(), kill);
    }

    private static String parsePid(String result) {
        if (result == null) {
            return null;
        }
        String splitStr = result.contains("\r\n") ? "\r\n" : "\n";
        String[] arr = result.split(splitStr);
        Optional<String> optional = Arrays.stream(arr).filter(s -> s.endsWith("(LISTEN)")).findFirst();
        if (optional.isPresent()) {
            String str = optional.get();
            str = str.replaceAll("\\s+", " ");
            String[] arr2 = str.split(" ");
            if (arr2.length > 2) {
                return StringUtils.isNumeric(arr2[1]) ? arr2[1] : null;
            }
        }
        return null;
    }
}